'use strict';


goog.provide('Blockly.Arduino.Rais_MixlyLib');
goog.require('Blockly.Arduino');

//string to number and shift 
function nsft(num){
	return '(' + num  + ')-1';
}

//check if Chinese comma or invaild syntax
function commaCheck(str){
	var hasCNComma = false;
	var hasTailComma = false;
	var hasRepeatComma = false;
	
	//if has Chinese comma
	if(str.trim() != ''){
		if(str.indexOf('，') != -1)				hasCNComma = true;
		if(str.trim().charAt(str.length - 1) == ',' || str.trim().charAt(0)  == ','){
			hasTailComma = true;
		}
		var arr = str.split(',');
		for(var i = 0; i < arr.length ; i++){
			if(arr[i].trim() == '')  {
				hasRepeatComma = true;
				break;
			}
		}
	}	
	return [hasCNComma, hasTailComma, hasRepeatComma];
}

//Rais_DuXingS&T -------------------------------------------------//

Blockly.Arduino.run_motor = function(){
	Blockly.Arduino.definitions_['include_Rais_DuXingS&T'] = '#include <Rais_Car.h>';
	
	var getMotorIndex = this.getFieldValue('motor_index');
	var getMotorSpeed = Blockly.Arduino.valueToCode(this, 'motor_speed', Blockly.Arduino.ORDER_ATOMIC);
	var code = getMotorIndex + ' = ' + getMotorSpeed + ';\n';
	return code;
}

Blockly.Arduino.get_speed = function(){
	Blockly.Arduino.definitions_['include_Rais_DuXingS&T'] = '#include <Rais_Car.h>';
	
	var getMotorIndex = this.getFieldValue('motor_index');
	var code = getMotorIndex + '.getSpeed()';
	return [code, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.run_car = function(){
	Blockly.Arduino.definitions_['include_Rais_DuXingS&T'] = '#include <Rais_Car.h>';
	
	var speed = Blockly.Arduino.valueToCode(this, 'motor_speed', Blockly.Arduino.ORDER_ATOMIC);
	var dir	  = Blockly.Arduino.valueToCode(this, 'motor_direction', Blockly.Arduino.ORDER_ATOMIC);
	var code  = 'dxcar(' + speed +', ' + dir + ');\n';
	return code;
}

Blockly.Arduino.set_wheels = function(){
	Blockly.Arduino.definitions_['include_Rais_DuXingS&T'] = '#include <Rais_Car.h>';
	
	var theLWheel = this.getFieldValue('theLWheel');
	var code = 'dxcar.setWheels(' + theLWheel + ');\n';
	return code;
}

Blockly.Arduino.set_rotation = function(){
	Blockly.Arduino.definitions_['include_Rais_DuXingS&T'] = '#include <Rais_Car.h>';
	var theWheel = this.getFieldValue('theWheel') == 'R' ? 'RIGHT_WHEEL' : 'LEFT_WHEEL' ;
	var rotation = this.getFieldValue('rotation');
	return 'dxcar.setRotation(' + theWheel + ', ' + rotation +');\n';
}

Blockly.Arduino.get_wheel_speed = function(){
	Blockly.Arduino.definitions_['include_Rais_DuXingS&T'] = '#include <Rais_Car.h>';
	
	var theWheel = this.getFieldValue('theWheel');
	var code = 'dxcar.get' + theWheel + 'Speed()';
	return [code, Blockly.Arduino.ORDER_ATOMIC];
}

//Rais_Deque -----------------------------------------------------//

Blockly.Arduino.data_types = function(){
	return [this.getFieldValue('type') + this.getFieldValue('rp'), Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.call_methods = function(){
	return [this.getFieldValue("dot_"), Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.user_defined_type = function(){
	return [this.getFieldValue('type_name'), Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.create_linkedlist = function(){
	var dataType = Blockly.Arduino.valueToCode(this, 'data_type', Blockly.Arduino.ORDER_ATOMIC);
	var name = this.getFieldValue('list_name'); 
	Blockly.Arduino.definitions_['include_Rais_LinkedList'] = '#include <Rais_LinkedList.h>\n';
	Blockly.Arduino.definitions_['def_linkedlist_' +  name] = 'rais::LinkedList<' + dataType + '> ' + name + ';\n';

	return '';
}

Blockly.Arduino.get_length = function(){
	return [this.getFieldValue('list_name') + '.getLength()', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.push = function(){
	return this.getFieldValue('list_name') + '.push(' +  Blockly.Arduino.valueToCode(this, 'new_element', Blockly.Arduino.ORDER_ATOMIC) + ');\n';
}
Blockly.Arduino.unshift = function(){
	return this.getFieldValue('list_name') + '.unshift(' +  Blockly.Arduino.valueToCode(this, 'new_element', Blockly.Arduino.ORDER_ATOMIC) + ');\n';
}
Blockly.Arduino.add = function(){
	return this.getFieldValue('list_name') + '.add(' + Blockly.Arduino.valueToCode(this, 'element_index', Blockly.ORDER_ATOMIC) + ', ' + Blockly.Arduino.valueToCode(this, 'new_element', Blockly.Arduino.ORDER_ATOMIC) + ');\n';
}

Blockly.Arduino.get_l = function(){
	//return lvalue
	var index = nsft( Blockly.Arduino.valueToCode(this, 'element_index', Blockly.Arduino.ORDER_ATOMIC) );
	var	dot = Blockly.Arduino.valueToCode(this, 'dot', Blockly.Arduino.ORDER_ATOMIC);
	return this.getFieldValue('list_name') + '[' + index + ']' + dot + ';\n';
}

Blockly.Arduino.get_r = function(){
	//return rvalue
	var index = nsft( Blockly.Arduino.valueToCode(this, 'element_index', Blockly.Arduino.ORDER_ATOMIC) );
	var	dot = Blockly.Arduino.valueToCode(this, 'dot', Blockly.Arduino.ORDER_ATOMIC);
	return [this.getFieldValue('list_name') + '[' + index + ']' + dot, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.shift_l = function(){
	var	dot = Blockly.Arduino.valueToCode(this, 'dot', Blockly.Arduino.ORDER_ATOMIC);
	return this.getFieldValue('list_name') + '.shift()' + dot + ';\n';
}
Blockly.Arduino.shift_r = function(){
	var	dot = Blockly.Arduino.valueToCode(this, 'dot', Blockly.Arduino.ORDER_ATOMIC);
	return [this.getFieldValue('list_name') + '.shift()' + dot, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pop_l = function(){
	var	dot = Blockly.Arduino.valueToCode(this, 'dot', Blockly.Arduino.ORDER_ATOMIC);
	return this.getFieldValue('list_name') + '.pop()' + dot + ';\n';

}
Blockly.Arduino.pop_r = function(){
	var	dot = Blockly.Arduino.valueToCode(this, 'dot', Blockly.Arduino.ORDER_ATOMIC);
	return [this.getFieldValue('list_name') + '.pop()' + dot, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.del_element = function(){
	return this.getFieldValue('list_name') + '.del(' + nsft(Blockly.Arduino.valueToCode(this, 'element_index', Blockly.ORDER_ATOMIC)) + ');\n';
}
Blockly.Arduino.clear_list = function(){
	return this.getFieldValue('list_name') + '.clear();\n';
}

//Rais_MatrixLED ---------------------------------------------------//
Blockly.Arduino.point_states = function(){
	return [this.getFieldValue("point_state"), Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.create_matrixLED = function(){
	Blockly.Arduino.definitions_['include_Rais_MatrixLED']	= "#include <Rais_MatrixLED.h>";
	var name = this.getFieldValue("mat_name");
	var pins = Blockly.Arduino.valueToCode(this, "cs_pin", Blockly.Arduino.ORDER_ATOMIC) + ", "
			 + Blockly.Arduino.valueToCode(this, "wr_pin", Blockly.Arduino.ORDER_ATOMIC) + ", "
			 + Blockly.Arduino.valueToCode(this, "data_pin", Blockly.Arduino.ORDER_ATOMIC);
	
	Blockly.Arduino.definitions_['def_MatrixLED' + name] = "rais::MatrixLED<> " + name + "(" + pins + ");\n"; 
	return "";
}



Blockly.Arduino.get_point_matrix = function(){
	var name = this.getFieldValue("mat_name");
	var coord = nsft( Blockly.Arduino.valueToCode(this, "p_x", Blockly.Arduino.ORDER_ATOMIC) ) + ", "
			  + nsft( Blockly.Arduino.valueToCode(this, "p_y", Blockly.Arduino.ORDER_ATOMIC) );
	return [name + "(" + coord + ")", Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.set_point_matrix = function(){
	var name = this.getFieldValue("mat_name");
	var coord_state = nsft( Blockly.Arduino.valueToCode(this, "p_x", Blockly.Arduino.ORDER_ATOMIC) ) + ", "
					+ nsft( Blockly.Arduino.valueToCode(this, "p_y", Blockly.Arduino.ORDER_ATOMIC) ) + ", "
					+ Blockly.Arduino.valueToCode(this, "p_state", Blockly.Arduino.ORDER_ATOMIC);
	var code = name + "(" + coord_state + ");\n";
	if(this.getFieldValue("paint_now") == "TRUE") code += (name + ".paint();\n"); 
	return code;
}

//removed.
// Blockly.Arduino.set_line_matrix = function(){
	// Blockly.Arduino.definitions_['include_Rais_Utils'] = "#include <Rais_Utils.h>";
	// var name = this.getFieldValue("mat_name");
	// var line_y = nsft( Blockly.Arduino.valueToCode(this, "line_y", Blockly.Arduino.ORDER_ATOMIC) );
	// var num = Blockly.Arduino.valueToCode(this, "num", Blockly.Arduino.ORDER_ATOMIC);
	//// num += (this.getFieldValue("inputs_bin") == "TRUE") ? "_b" : "UL" ;
	// if(this.getFieldValue("inputs_bin") == "TRUE") num = '' + num + '_b';	//非二进制不再做处理
	// var code = name + ".setln(" + line_y + ", " + num + ");\n";
	// if(this.getFieldValue("paint_now") == "TRUE") code += (name + ".paint();\n"); 
	// return code;
// }

Blockly.Arduino.fill_matrix = function(){
	var name = this.getFieldValue("mat_name");
	var state = Blockly.Arduino.valueToCode(this, "state", Blockly.Arduino.ORDER_ATOMIC);
	var x = Blockly.Arduino.valueToCode(this, "x", Blockly.Arduino.ORDER_ATOMIC);				x = x ? nsft(x) : '0'; 
	var y = Blockly.Arduino.valueToCode(this, "y", Blockly.Arduino.ORDER_ATOMIC);	 			y = y ? nsft(y) : '0';
	var end_x = Blockly.Arduino.valueToCode(this, "end_x", Blockly.Arduino.ORDER_ATOMIC);		end_x = end_x ? nsft(end_x) : '31';
	var end_y = Blockly.Arduino.valueToCode(this, "end_y", Blockly.Arduino.ORDER_ATOMIC);		end_y = end_y ? nsft(end_y) : (name + '.screenNum()*8-1');
	
	var code = this.getFieldValue("mat_name") + ".fill(" + state + ', ' + x + ', ' + y + ', ' + end_x + ', ' + end_y + ');\n';
	if(this.getFieldValue("paint_now") == "TRUE") code += (name + ".paint();\n");
	return code;
}

Blockly.Arduino.set_string_matrix = function(){
	Blockly.Arduino.definitions_["include_Rais_CharacterMatrix"] = "#include <Rais_CharacterMatrix.h>	//for String drawing function";
	
	var name = this.getFieldValue("mat_name");
	var str = Blockly.Arduino.valueToCode(this, "str", Blockly.Arduino.ORDER_ATOMIC);
	
	var x = Blockly.Arduino.valueToCode(this, "x", Blockly.Arduino.ORDER_ATOMIC);				x = x ? nsft(x) : '0'; 
	var y = Blockly.Arduino.valueToCode(this, "y", Blockly.Arduino.ORDER_ATOMIC);	 			y = y ? nsft(y) : '0';
	var end_x = Blockly.Arduino.valueToCode(this, "end_x", Blockly.Arduino.ORDER_ATOMIC);		end_x = end_x ? nsft(end_x) : '31';
	var end_y = Blockly.Arduino.valueToCode(this, "end_y", Blockly.Arduino.ORDER_ATOMIC);		end_y = end_y ? nsft(end_y) : (name + '.screenNum()*8-1');
	
	var shft_x = Blockly.Arduino.valueToCode(this, "shft_x", Blockly.Arduino.ORDER_ATOMIC);		shft_x = shft_x ? nsft(shft_x) : '0';
	var shft_y = Blockly.Arduino.valueToCode(this, "shft_y", Blockly.Arduino.ORDER_ATOMIC);		shft_y = shft_y ? nsft(shft_y) : '0';
	
	var code = "drawStr(" + name + ", operator(), " + str + ", " + x + ", " + y + ", " + end_x + ", " + end_y  + ", " + shft_x + ", " + shft_y + ");\n";
	if(this.getFieldValue("paint_now") == "TRUE") code += (name + ".paint();\n");
	return code;
}

Blockly.Arduino.set_image_matrix = function(){
	Blockly.Arduino.definitions_["include_Rais_MixlyEasy"] = "#include <Rais_MixlyEasy.h>	//for Image drawing function";
	var name = this.getFieldValue("mat_name");
	var img = Blockly.Arduino.valueToCode(this, "img", Blockly.Arduino.ORDER_ATOMIC);
	var x = Blockly.Arduino.valueToCode(this, "x", Blockly.Arduino.ORDER_ATOMIC);				x = x ? nsft(x) : '0'; 
	var y = Blockly.Arduino.valueToCode(this, "y", Blockly.Arduino.ORDER_ATOMIC);	 			y = y ? nsft(y) : '0';
	var end_x = Blockly.Arduino.valueToCode(this, "end_x", Blockly.Arduino.ORDER_ATOMIC);		end_x = end_x ? nsft(end_x) : '31';
	var end_y = Blockly.Arduino.valueToCode(this, "end_y", Blockly.Arduino.ORDER_ATOMIC);		end_y = end_y ? nsft(end_y) : (name + '.screenNum()*8-1');
	
	var shft_x = Blockly.Arduino.valueToCode(this, "shft_x", Blockly.Arduino.ORDER_ATOMIC);		shft_x = shft_x ? nsft(shft_x) : '0';
	var shft_y = Blockly.Arduino.valueToCode(this, "shft_y", Blockly.Arduino.ORDER_ATOMIC);		shft_y = shft_y ? nsft(shft_y) : '0';
	
	var code = "drawPgmImgToMat(" + name + ", " + img + ", " + x + ", " + y + ", " + end_x + ", " + end_y + ", " + shft_x + ", " + shft_y + ");\n";
	if(this.getFieldValue("paint_now") == "TRUE") code += (name + ".paint();\n");
	return code;
	
}

Blockly.Arduino.paint_matrix = function(){
	return this.getFieldValue("mat_name") + ".paint();\n";
}

Blockly.Arduino.clear_matrix = function(){
	var state = Blockly.Arduino.valueToCode(this, "state", Blockly.Arduino.ORDER_ATOMIC);
	var code = this.getFieldValue("mat_name") + ".clear(" + state + ");\n";
	if(this.getFieldValue("paint_now") == "TRUE") code += (this.getFieldValue("mat_name") + ".paint();\n"); 
	return code;
}

Blockly.Arduino.blink_matrix = function(){
	return this.getFieldValue("mat_name") + ".blink(" + this.getFieldValue("blink_state") + ");\n";
}

Blockly.Arduino.set_brightness_matrix = function(){
	return this.getFieldValue("mat_name") + ".setBrightness(" + nsft(Blockly.Arduino.valueToCode(this, "brightness", Blockly.Arduino.ORDER_ATOMIC)) + ");\n";
}

Blockly.Arduino.set_system = function(){
	return this.getFieldValue("mat_name") + '.setSystem(' + this.getFieldValue("system_state") + ');\n';
}

function getStrArgsNum(str){return str.split(',').length;}
  
Blockly.Arduino.create_polyMatrixLED = function(){
	Blockly.Arduino.definitions_['include_Rais_MixlyEasy']	= '#include <Rais_MixlyEasy.h>';
	Blockly.Arduino.definitions_['include_Rais_MatrixLED']	= '#include <Rais_MatrixLED.h>';
	var name = this.getFieldValue("mat_name");
	var mat_num = this.getFieldValue("mat_num");
	var pins = Blockly.Arduino.valueToCode(this, "cs_pin", Blockly.Arduino.ORDER_ATOMIC) + ", "
			 + Blockly.Arduino.valueToCode(this, "wr_pin", Blockly.Arduino.ORDER_ATOMIC);
	var datapins = this.getFieldValue("mat_data_pins");
	var checkedData = commaCheck(datapins);
	this.hasCNComma = checkedData[0];
	this.hasTailComma= checkedData[1];
	this.hasRepeatComma = checkedData[2];

	if(mat_num.trim() == '') mat_num = getStrArgsNum(datapins) + '';
	Blockly.Arduino.definitions_['def_polyMatrixLED' + name] = "rais::MatrixLED<" + mat_num + "> " + name + "(" + pins + ", " +  datapins + ");\n";
	return "";
}


//Rais_Graph -------------------------------------------------//
//2020.4.12, 2:42.

Blockly.Arduino.orthogonal_dir = function(){
	return [this.getFieldValue('dir'), Blockly.Arduino.ORDER_ATOMIC];
}
Blockly.Arduino.orthogonal_dir_no_tip = function(){
	return [this.getFieldValue('dir'), Blockly.Arduino.ORDER_ATOMIC];
}
Blockly.Arduino.orthogonal_turning = function(){
	return [this.getFieldValue('dir'), Blockly.Arduino.ORDER_ATOMIC];
}

function getGraphMaxVertexIdx(str){
	var sentences = str.split(/[\{\;\}]/g);
	var maxVertexIdx = 0;
	for(var i = 0; i < sentences.length; i++){
		if(sentences[i].indexOf('link(') != -1){
			var args = sentences[i].split(/[\(\,\)]/g);
			if(!isNaN(parseInt(args[2])) && !isNaN(parseInt(args[5])) ){
				maxVertexIdx = Math.max(maxVertexIdx,parseInt(args[2]), parseInt(args[5]) );
			}
		}else {
			if(sentences[i].indexOf('links(') != -1){
				var args = sentences[i].split(/[\(\,\)]/g);
				for(var j = 0; j < args.length; j++){
					if(!isNaN(parseInt(args[j]) ) ){
						maxVertexIdx = Math.max(maxVertexIdx, parseInt(args[j]) );
					}
				}
			}
		}
	}
	return maxVertexIdx;
}

Blockly.Arduino.create_graph = function(){
	Blockly.Arduino.definitions_['include_Rais_Graph'] = '#include <Rais_Graph.h>';
	var name =  this.getFieldValue("graph_name");
	var vertexNum = Blockly.Arduino.valueToCode(this, "vertexNum", Blockly.Arduino.ORDER_ATOMIC);
	var maxEdgeNum = Blockly.Arduino.valueToCode(this, "maxEdgeNum", Blockly.Arduino.ORDER_ATOMIC);
	var build = Blockly.Arduino.statementToCode(this, 'build');
	if(vertexNum.trim() == '') vertexNum = (getGraphMaxVertexIdx(build)) + '';
	var lambda_build = '';
	if(build.trim() != '') lambda_build = ', [](rais::Graph<>& ' + name + '){\n' + build + '}'; 
	Blockly.Arduino.definitions_['def_graph_' + name] = 
	'rais::Graph<> ' + name + '(' + vertexNum + ', ' + maxEdgeNum + lambda_build + ');\n' + 
	'rais::PathFinder<> pf_' + name + '(' + name + ');\n';
	
	return '';
}


Blockly.Arduino.create_orthogonal_graph = function(){
	Blockly.Arduino.definitions_['include_Rais_Graph'] = '#include <Rais_Graph.h>';
	var name =  this.getFieldValue("graph_name");
	var vertexNum = Blockly.Arduino.valueToCode(this, "vertexNum", Blockly.Arduino.ORDER_ATOMIC);
	var build = Blockly.Arduino.statementToCode(this, 'build');
	if(vertexNum.trim() == '') vertexNum = (getGraphMaxVertexIdx(build)) + '';
	var lambda_build = '';
	if(build.trim() != '') lambda_build = ', [](rais::OrthogonalGraph<>& ' + name + '){\n' + build + '}'; 
	Blockly.Arduino.definitions_['def_orthogonal_graph_' + name] =	
	'rais::OrthogonalGraph<> ' + name + '(' + vertexNum + lambda_build + ');\n' + 
	'rais::OrthogonalPathFinder<> pf_' + name + '(' + name + ');\n';
	
	return '';
}

// var graph_builder_param = 'g.';

Blockly.Arduino.graph_link = function(){
	var name = this.getFieldValue("graph_name") || '';
	var host_idx = nsft( Blockly.Arduino.valueToCode(this, "host_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var adj_idx = nsft( Blockly.Arduino.valueToCode(this, "adj_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var host_edge_idx = Blockly.Arduino.valueToCode(this, "host_edge_idx", Blockly.Arduino.ORDER_ATOMIC);
	var adj_edge_idx = Blockly.Arduino.valueToCode(this, "adj_edge_idx", Blockly.Arduino.ORDER_ATOMIC);
	
	var code = 'link(' + host_idx + ', ' + adj_idx + ', ' + host_edge_idx + ', ' + adj_edge_idx + ');\n';
	// if(this.isInBuild)	return graph_builder_param + code;
	// else				
	return name + '.' + code;
}

Blockly.Arduino.orthogonal_graph_link = function(){
	var name = this.getFieldValue("graph_name") || '';
	var host_idx = nsft( Blockly.Arduino.valueToCode(this, "host_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var adj_idx = nsft( Blockly.Arduino.valueToCode(this, "adj_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var host_edge_idx = Blockly.Arduino.valueToCode(this, "host_edge_idx", Blockly.Arduino.ORDER_ATOMIC);
	var code =  'link(' + host_idx + ', ' + adj_idx + ', ' + host_edge_idx + ');\n';
	// if(this.isInBuild)	return graph_builder_param + code;
	// else				
	return name + '.' + code;
}

function numsShft(nums_str){
	var nums_arr = nums_str.split(',');
	var ret_str = '';
	for(var i = 0; i < nums_arr.length - 1; i++){
		// if(!isNaN(parseInt(nums_arr[i]))) {ret_str += ( nsft(parseInt(nums_arr[i])) + ', ') };
		if(nums_arr[i].trim() != '') {ret_str += ( nsft(nums_arr[i].trim()) + ', ') };
		
	}
	//if(!isNaN(parseInt(nums_arr[ nums_arr.length - 1]))) {ret_str += nsft(parseInt(nums_arr[ nums_arr.length - 1])) };
	if(nums_arr[nums_arr.length - 1].trim() != '') {ret_str += nsft(nums_arr[ nums_arr.length - 1].trim() ) };
	
	return ret_str;
}

Blockly.Arduino.orthogonal_graph_links = function(){
	var name = this.getFieldValue("graph_name");
	var links_direction_arr = this.getFieldValue("links_direction_arr");
	var vs = numsShft( this.getFieldValue("Vs") );
	var checkResult = commaCheck(this.getFieldValue("Vs"));
	this.hasCNComma = checkResult[0];
	this.hasTailComma = checkResult[1];
	this.hasRepeatComma = checkResult[2];
	
	var code = 'links(' + links_direction_arr + ', ' + vs + ');\n';
	// if(this.isInBuild)	return graph_builder_param + code;
	// else				
	return name + '.' + code;
}

Blockly.Arduino.graph_cut = function(){
	var name = this.getFieldValue("graph_name");
	var host_idx = nsft( Blockly.Arduino.valueToCode(this, "host_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var host_edge_idx = Blockly.Arduino.valueToCode(this, "host_edge_idx", Blockly.Arduino.ORDER_ATOMIC);
	var code = "cut(" + host_idx + ', ' + host_edge_idx + ');\n';
	// if(this.isInBuild)	return graph_builder_param + code;
	// else		
	return name + '.' + code;
}

Blockly.Arduino.graph_get_edge_idx = function(){
	var name = this.getFieldValue("graph_name");
	var host_idx = nsft( Blockly.Arduino.valueToCode(this, "host_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var adj_idx = nsft( Blockly.Arduino.valueToCode(this, "adj_idx", Blockly.Arduino.ORDER_ATOMIC) );
	var code = 'getEIndex('+ host_idx + ', ' + adj_idx + ')';
	// if(this.isInBuild)	return [graph_builder_param + code, Blockly.Arduino.ORDER_ATOMIC];
	// else				
	return [name + '.' + code, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pf_set = function(){
	var name = 'pf_' + this.getFieldValue("graph_name");
	var idx = nsft( Blockly.Arduino.valueToCode(this, "idx", Blockly.Arduino.ORDER_ATOMIC) );
	var s_t = this.getFieldValue("s_t");
	return name + '.set' + s_t +'(' + idx + ');\n';
}

Blockly.Arduino.pf_get = function(){
	var name = 'pf_' + this.getFieldValue("graph_name");
	var s_t = this.getFieldValue("s_t");
	return ['(' + name + '.get'+ s_t +'().index+1)',  Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pf_find = function(){
	var name = 'pf_' + this.getFieldValue("graph_name");
	return name + '.find();\n';
}

Blockly.Arduino.pf_finding_result = function(){
	var name = 'pf_' + this.getFieldValue("graph_name");
	return [name + '.getResult()', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pf_finding_result_constant = function(){
	var cst = this.getFieldValue("result_constant");
	return [cst, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pf_path_length = function(){
	var name = 'pf_' + this.getFieldValue("graph_name");
	return [name + '.path.getLength()', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pf_path_get = function(){
	var name = 'pf_' + this.getFieldValue("graph_name");
	var idx = nsft( Blockly.Arduino.valueToCode(this, "path_idx", Blockly.Arduino.ORDER_ATOMIC) );
	return ['(' + name + '.path[' + idx + '].index + 1)', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.get_turning_dir = function(){
	Blockly.Arduino.definitions_['include_Rais_MixlyEasy'] = '#include <Rais_MixlyEasy.h>'
	var fasing = Blockly.Arduino.valueToCode(this, 'fasing', Blockly.Arduino.ORDER_ATOMIC);
	var abs_turning_dir = Blockly.Arduino.valueToCode(this, 'abs_turning_dir', Blockly.Arduino.ORDER_ATOMIC);
	return ['get_turning_dir(' + fasing + ', ' + abs_turning_dir + ')' , Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.get_o_turningbehavior = function(){
	var name = this.getFieldValue('graph_name');
	var last = Blockly.Arduino.valueToCode(this, 'o_last_vertex');
	var current = Blockly.Arduino.valueToCode(this, 'o_current_vertex');
	var next = Blockly.Arduino.valueToCode(this, 'o_next_vertex');
	return ['pf_' + name + '.getTurningBehavior((' + last + ')-1, (' + current + ')-1, (' + next + ')-1)', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.builtin_graph_logistics = function(){
	Blockly.Arduino.definitions_['include_Rais_Graph'] = '#include <Rais_Graph.h>';
	var name =  this.getFieldValue("graph_name");
	var builds = Blockly.Arduino.statementToCode(this, 'builds');
	var lambda_build = '';
	if(builds.trim() != '') lambda_build = ', [](rais::OrthogonalGraph<>& ' + name + '){\n' + builds + '}'; 
	Blockly.Arduino.definitions_['def_orthogonal_graph_' + name] =	
	'rais::OrthogonalGraph<> ' + name + '(24' + lambda_build + ');\n' + 
	'rais::OrthogonalPathFinder<> pf_' + name + '(' + name + ');\n';
	return '';
}

//Rais_LineTracker --------------------------------------------------------------------------------------//

Blockly.Arduino.motion_pwr = function(){return ["pwr", Blockly.Arduino.ORDER_ATOMIC];}
Blockly.Arduino.motion_dir = function(){return ["dir", Blockly.Arduino.ORDER_ATOMIC];}
Blockly.Arduino.is_state_return_switch = function(){
	return [this.getFieldValue("state"), Blockly.Arduino.ORDER_ATOMIC];
}
Blockly.Arduino.is_state_return = function(){
	return 'return ' + Blockly.Arduino.valueToCode(this, "isState", Blockly.Arduino.ORDER_ATOMIC) + ';\n';
}

var func_override_head = '  //@not been overrided: ';
var func_override_ics= func_override_head + 'isCorrectingState';
var func_override_iis = func_override_head + 'isInertiaState';
var func_override_ns = func_override_head + 'normalState';
var func_override_cs = func_override_head + 'correctingState';
var func_override_is	 = func_override_head + 'inertiaState';
var func_override_es = func_override_head + 'exceptionState';
var func_override_eds = func_override_head + 'endState';

Blockly.Arduino.create_line_tracker = function(){
	Blockly.Arduino.definitions_["include_Rais_MixlyEasy"] = "#include <Rais_MixlyEasy.h>";
	Blockly.Arduino.definitions_["include_Rais_LineTracker"] = "#include <Rais_LineTracker.h>";
	
	var name = this.getFieldValue("name");
	var sens_num = this.getFieldValue("sens_num");
	var pins = this.getFieldValue("pins");
	var checkResult = commaCheck(pins);
	this.hasCNComma = checkResult[0];
	this.hasTailComma = checkResult[1];
	this.hasRepeatComma = checkResult[2];
	
	var blackState = Blockly.Arduino.valueToCode(this, "pins_black_state", Blockly.Arduino.ORDER_ATOMIC);
	if(!sens_num || sens_num.trim() == '') sens_num = getStrArgsNum(pins);
	var centerLine = sens_num;
	var motionCodes = Blockly.Arduino.statementToCode(this, "motion");
	var isNormalStateCodes = Blockly.Arduino.statementToCode(this, "isNormalState");

	Blockly.Arduino.definitions_['def_LineTracker_pins_array_' + name] = 'byte lineTrackerPinsArray_' + name + '[] = {' + pins + '};\n';
	
	Blockly.Arduino.definitions_["def_LineTracker_" + name] = 
	'class CLineTracker_' + name + ': public LineTracker<' + sens_num + '> {\n'	+
	'  public:\n' 																+
	'  CLineTracker_' + name +'(byte pins[], bool blackState, unsigned int centerLine): LineTracker<' + sens_num + '>(pins, blackState, centerLine){}\n' +
	'  \n'																	+
	'  virtual void motion(int pwr, int dir) {\n'							+
	motionCodes																+
	'  \n'																	+
	'  }\n'																	+
	'  \n'																	+
	'  virtual bool isNormalState(){\n'										+
	isNormalStateCodes														+
	'  \n'																	+
	'  }\n'																	+
	'  \n'																	+
	'  //for js string replacement, DO NOT change or remove these!\n'		+
	func_override_ics	+ '\n' +
	func_override_iis 	+ '\n' +	
	func_override_ns	+ '\n' +
	func_override_cs	+ '\n' +
	func_override_is	+ '\n' +
	func_override_es	+ '\n' +
	func_override_eds	+ '\n' +
	'\n'																	+
	'} ' + name + '(lineTrackerPinsArray_' + name + ', ' + blackState + ', '  + centerLine + ');\n' +
	'\n';
	return '';
}


Blockly.Arduino.create_traveller = function(){
	Blockly.Arduino.definitions_["include_Rais_MixlyEasy"] = "#include <Rais_MixlyEasy.h>";
	Blockly.Arduino.definitions_["include_Rais_LineTracker"] = "#include <Rais_LineTracker.h>";
	
	var name = this.getFieldValue("name");
	var sens_num = this.getFieldValue("sens_num");
	var pins = this.getFieldValue("pins");
	var checkResult = commaCheck(pins);
	this.hasCNComma = checkResult[0];
	this.hasTailComma = checkResult[1];
	this.hasRepeatComma = checkResult[2];

	var pf = 'pf_' + this.getFieldValue('graph_name');
	var fasing = Blockly.Arduino.valueToCode(this, 'fasing', Blockly.Arduino.ORDER_ATOMIC);
	var blackState = Blockly.Arduino.valueToCode(this, "pins_black_state", Blockly.Arduino.ORDER_ATOMIC);
	if(!sens_num || sens_num.trim() == '') sens_num = getStrArgsNum(pins);
	var centerLine = sens_num;
	var motionCodes = Blockly.Arduino.statementToCode(this, "motion");
	var isNormalStateCodes = Blockly.Arduino.statementToCode(this, "isNormalState");
	var isReachingVertexStateCodes = Blockly.Arduino.statementToCode(this, "isReachingVertexState");
	var vertexType = Blockly.Arduino.definitions_['def_builtin_logistics_' +  this.getFieldValue('graph_name')] ? 'LogisticsVertex' : 'Vertex';
	
	Blockly.Arduino.definitions_['def_LineTracker_pins_array_' + name] = 'byte lineTrackerPinsArray_' + name + '[] = {' + pins + '};\n';
	
	Blockly.Arduino.definitions_["def_LineTracker_" + name] = 
	'class CLineTracker_' + name + ': public Traveller<' + sens_num + ', ' + vertexType +'> {\n'	+
	'  public:\n' 															+
	'  CLineTracker_' + name +'(byte pins[], PathFinding<' + vertexType + '>& guide_, bool blackState, byte fasing, unsigned int centerLine)\n' +
	'    :Traveller<' + sens_num + ', ' + vertexType +'>(pins, guide_, blackState, fasing, centerLine){}\n' +
	'  \n'																	+
	'  virtual void motion(int pwr, int dir) {\n'							+
	motionCodes																+
	'  \n'																	+
	'  }\n'																	+
	'  \n'																	+
	'  virtual bool isNormalState(){\n'										+
	isNormalStateCodes														+
	'  \n'																	+
	'  }\n'																	+
	'  \n'																	+
	'  virtual bool isReachingVertexState(){\n'								+
	isReachingVertexStateCodes												+
	'  \n'																	+
	'  }\n'																	+
	'  \n'																	+
	'  //for js string replacement, DO NOT change or remove these!\n'		+
	func_override_ics	+ '\n' +
	func_override_iis 	+ '\n' +
	func_override_ns	+ '\n' +
	func_override_cs	+ '\n' +
	func_override_is	+ '\n' +
	func_override_es	+ '\n' +
	func_override_eds	+ '\n' +
	'\n'																	+
	'} ' + name + '(lineTrackerPinsArray_' + name + ', '+ pf +', ' + blackState + ', '+ fasing +', '  + centerLine + ');\n' +
	'\n';
	return '';
}


Blockly.Arduino.line_tracker_run = function(){
	if(this.isInCls){
		return 'run();\n';
	}else {
		var name = this.getFieldValue("name");
		return name + '.run();\n';
	}
}

Blockly.Arduino.line_tracker_set = function(){
	var sets = this.getFieldValue("sets");
	var val = Blockly.Arduino.valueToCode(this, 'value', Blockly.Arduino.ORDER_ATOMIC);
	if(this.isInCls){
		if(sets == 'setPower' || sets == 'setCorrectingDegree'){
			return sets + '(' + val + ');\n';
		}else {
			return sets + ' = ' + val + ';\n';
		}
	}else {	
		var name = this.getFieldValue("name");
		if(sets == 'setPower' || sets == 'setCorrectingDegree'){
			return name + '.' + sets + '(' + val + ');\n';
		}else {
			return name + '.' + sets + ' = ' + val + ';\n';
		}
	}
}

Blockly.Arduino.line_tracker_get = function(){
	var gets = this.getFieldValue("gets");
	if(this.isInCls){
		return  [gets, Blockly.Arduino.ORDER_ATOMIC];
	}else {
		return [this.getFieldValue("name") + '.' + gets, Blockly.Arduino.ORDER_ATOMIC];
	}
}

Blockly.Arduino.line_tracker_get_sens = function(){
	var idx = nsft( Blockly.Arduino.valueToCode(this, 'sens_idx', Blockly.Arduino.ORDER_ATOMIC) );
	if(this.isInCls){
		return ['sens[' + idx + ']' , Blockly.Arduino.ORDER_ATOMIC];
	}else {
		return [this.getFieldValue("name") + '.sens[' + idx + ']' , Blockly.Arduino.ORDER_ATOMIC];
	}
}

Blockly.Arduino.line_tracker_override_is_state_fun = function(){
	var name = this.getFieldValue("name");
	if(!Blockly.Arduino.definitions_['def_LineTracker_' + name]) return "";
	var fun = this.getFieldValue("fun");
	var codes = '  virtual bool ' + fun + '(){\n'	+
		Blockly.Arduino.statementToCode(this, "codes")	+
	'  \n'										+
	'  }\n';
	Blockly.Arduino.definitions_['def_LineTracker_' + name] = 
		Blockly.Arduino.definitions_['def_LineTracker_' + name].replace(func_override_head + fun,  codes);

	return "";
}

Blockly.Arduino.if_left_vertex_switch = function(){
	return [this.getFieldValue("isState"), Blockly.Arduino.ORDER_ATOMIC];
}
Blockly.Arduino.if_left_vertex = function(){
	var isState = Blockly.Arduino.valueToCode(this, "isState", Blockly.Arduino.ORDER_ATOMIC);
	return 'return ' + isState + ';\n';
}

Blockly.Arduino.line_tracker_override_state_fun = function(){
	var name = this.getFieldValue("name");
	if(!Blockly.Arduino.definitions_['def_LineTracker_' + name]) return "";
	var fun = this.getFieldValue("fun");
	var codes = '  virtual void ' + fun + '(){\n'	+
		Blockly.Arduino.statementToCode(this, "codes")	+
	'  \n'										+
	'  }\n';
	Blockly.Arduino.definitions_['def_LineTracker_' + name] = 
		Blockly.Arduino.definitions_['def_LineTracker_' + name].replace(func_override_head + fun,  codes);

	return "";
}

Blockly.Arduino.traveller_addTurningFunction = function(){
	var name = this.getFieldValue("name");
	if(!Blockly.Arduino.definitions_['def_LineTracker_' + name]) return "";
	var dir = Blockly.Arduino.valueToCode(this, "direction", Blockly.Arduino.ORDER_ATOMIC);
	var codes = Blockly.Arduino.statementToCode(this, "codes");
	Blockly.Arduino.definitions_['def_lineTracker_turningFunc_' + name + '_' + dir] = 
	'bool lineTrackerTurningFunc_' + name + '_' + dir + '(){\n'	+
	codes + 
	'\n'  +
	'}\n'+
	'\n';
	Blockly.Arduino.setups_['set_lineTracker_turningFunc' + name + '_' + dir] = 
	name + '.addTurningFunction(lineTrackerTurningFunc_'+ name + '_' + dir  + ', ' + dir + ');'; 
}

Blockly.Arduino.traveller_addTask = function(){
	var name = this.getFieldValue("name");
	var idx = nsft( Blockly.Arduino.valueToCode(this, "vertex_idx", Blockly.Arduino.ORDER_ATOMIC) );
	return name + '.addTask(' + idx + ');\n';
}



Blockly.Arduino.in_range = function(){
	Blockly.Arduino.definitions_['include_Rais_Utils'] = '#include <Rais_Utils.h>';
	var variable = Blockly.Arduino.valueToCode(this, "var", Blockly.Arduino.ORDER_ATOMIC);
	var downer = Blockly.Arduino.valueToCode(this, "downer", Blockly.Arduino.ORDER_ATOMIC);
	var upper    = Blockly.Arduino.valueToCode(this, "upper", Blockly.Arduino.ORDER_ATOMIC);
	return ['inRange(' + variable + ', ' + downer + ', ' + upper + ')' , Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.F_string = function(){
	var str = Blockly.Arduino.valueToCode(this, 'str', Blockly.Arduino.ORDER_ATOMIC);
	return ['F(' + str + ')' ,Blockly.Arduino.ORDER_ATOMIC];
	
}

Blockly.Arduino.statements_timing = function(){
	Blockly.Arduino.definitions_["include_Rais_Utils"] = '#include <Rais_Utils.h>';
	var unit = this.getFieldValue("unit");
	var code = Blockly.Arduino.statementToCode(this, "codes");
	return ['timing(' + unit + ', \n' + code + '\n)', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.pragma_optimize = function(){
	var arg = this.getFieldValue('arg');
	//using 'define_' as the key's head is for increasing this line of code's priority.
	Blockly.Arduino.definitions_['define_pragma_optimize'] = '#pragma GCC optimize(' + arg + ')'
	return '';
}

Blockly.Arduino.better_random_seed = function(){
	Blockly.Arduino.definitions_['include_Rais_Utils'] = '#include <Rais_Utils.h>';
	Blockly.Arduino.definitions_['include_EEPROM'] = '#include <EEPROM.h>';
	Blockly.Arduino.setups_['betterRandomSeed'] = 'betterRandomSeed(EEPROM);'; 
	return '';
}

Blockly.Arduino.binary_constant = function(){
	Blockly.Arduino.definitions_['include_Rais_Utils'] = '#include <Rais_Utils.h>';
	return [this.getFieldValue("bin_num").replace(/ /g, '') + '_b', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.abandon_retval = function(){
	var code = Blockly.Arduino.valueToCode(this, 'valblock', Blockly.Arduino.ORDER_ATOMIC);
	if(code.trim() == '') return '';
	return code + ';\n';
}

//field name id generate
function idGen(str){
	return str.replace(/[^\u0000-\u00FF]/g,function($0){return escape($0).replace(/(%u)(\w{4})/gi,"$2")});
}


Blockly.Arduino.yingxiaohao_generator = function(){
	var body = this.getFieldValue("body");
	var thing = this.getFieldValue("thing");
	var other_word = this.getFieldValue("other_word");
	var utf_8_text = Blockly.YING_XIAO_HAO_TEMPLATE.replace(/\\17/g, body).replace(/\\18/g, thing).replace(/\\19/g, other_word);
	return [utf_8_text, Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.yingxiaohao_generator_dynamic = function(){
	var body = Blockly.Arduino.valueToCode(this, 'body', Blockly.Arduino.ORDER_ATOMIC);
	var thing = Blockly.Arduino.valueToCode(this, 'thing', Blockly.Arduino.ORDER_ATOMIC); 
	var other_word = Blockly.Arduino.valueToCode(this, 'other_word', Blockly.Arduino.ORDER_ATOMIC);
	
	Blockly.Arduino.definitions_['define_yingxiaohao_template'] = 'static const PROGMEM char YXH_TEMPLATE[] = ' + Blockly.YING_XIAO_HAO_TEMPLATE + ';\n\
String yxhtext_replace(const String& body, const String& thing, const String& other_word) {\n  String tmp(YXH_TEMPLATE);\n  tmp.replace("\\17", body);\n  tmp.replace("\\18", thing);\n  tmp.replace("\\19", other_word);\n  return tmp;\n}'
	// var code = 'YXH_TEMPLATE.replace(\"\\17\", ' + body  + ').replace(\"\\18\", ' + thing + ').replace(\"\\19\", ' + other_word + ')';
	return ['yxhtext_replace(' + body + ', ' + thing + ', ' + other_word + ')', Blockly.Arduino.ORDER_ATOMIC];
	
}

Blockly.Arduino.block_dye = function(){
	this.setColour(this.getFieldValue("color") );
	return '';
}

Blockly.Arduino.block_dye_hex = function(){
	this.setColour("#" + this.getFieldValue("color_hex") );
	return '';
}

Blockly.Arduino.warning_contagion = function(){
	var text = this.getFieldValue("warning_text");
	if(text == "") text = null;
	this.setWarningText(text, "id_warning_magic");
	return '';
}

Blockly.Arduino.create_eight_buttons = function(){
	Blockly.Arduino.definitions_["include_Rais_BS818A_2_Parallel"] = '#include <Rais_BS818A_2_Parallel.h>';
	var name = this.getFieldValue("eightBtns_name");
	var b0 = Blockly.Arduino.valueToCode(this, 'B0', Blockly.Arduino.ORDER_ATOMIC);
	var b1 = Blockly.Arduino.valueToCode(this, 'B1', Blockly.Arduino.ORDER_ATOMIC);
	var b2 = Blockly.Arduino.valueToCode(this, 'B2', Blockly.Arduino.ORDER_ATOMIC);
	var b3 = Blockly.Arduino.valueToCode(this, 'B3', Blockly.Arduino.ORDER_ATOMIC);
	Blockly.Arduino.definitions_["create_eight_buttons_" + name] = 'rais::EightButtons ' + name + '(' + b0 + ', ' + b1 + ', ' + b2 + ', ' + b3 + ');\n';
	return "";
}

Blockly.Arduino.eight_btns_get_key = function(){
	return [this.getFieldValue("eightBtns_name") + '()', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.eight_btns_isTouched = function(){
	return [this.getFieldValue("eightBtns_name") + '.isTouched()', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.eight_btns_get_touch_time_len = function(){
	var name = this.getFieldValue("eightBtns_name");
	var btnIdx = this.getFieldValue("btnIdx");
	return [name + '.wait_released(' + btnIdx + ')', Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.eight_btns_wait_untils = function(){
	var name = this.getFieldValue("eightBtns_name");
	var btnIdx = this.getFieldValue("btnIdx");
	var waits_sign = this.getFieldValue("waits_sign");
	var callbackActions = Blockly.Arduino.statementToCode(this, 'callback_action');
	
	if(waits_sign != 'touched_until_released') {
		if(callbackActions != '') callbackActions = ', []{\n' + callbackActions + '}';
		return name + '.wait_' + waits_sign + '(' + btnIdx + callbackActions + ');\n';
	}else {
		if(callbackActions != '') callbackActions = '\n' + callbackActions;
		return name + '.wait_' + waits_sign + '(' + btnIdx + ', []{' + callbackActions + '});\n';
	}
}

Blockly.Arduino.eight_btns_return = function(){
	return 'return;\n';
}


//unused:
Blockly.Arduino.create_mat_data_32x8 = function(){
	Blockly.Arduino.definitions_['include_Rais_Utils'] = '#include <Rais_Utils.h>';
	var name = this.getFieldValue("mat_name");
	
	Blockly.Arduino.definitions_['def_mat_data_' + name] = 'mat32x8_t ' + name + ';\n';
	return '';
}

Blockly.Arduino.get_mat_data = function(){
	Blockly.Arduino.definitions_['include_Rais_Utils'] = '#include <Rais_Utils.h>';
	var name = this.getFieldValue("mat_name");
	var x = nsft(Blockly.Arduino.valueToCode(this, 'x', Blockly.Arduino.ORDER_ATOMIC));
	var y = nsft(Blockly.Arduino.valueToCode(this, 'y', Blockly.Arduino.ORDER_ATOMIC));
	return ['mget(' + name + ', ' + x + ', ' + y + ')' , Blockly.Arduino.ORDER_ATOMIC];
}

Blockly.Arduino.set_mat_data = function(){
	Blockly.Arduino.definitions_['include_Rais_Utils'] = '#include <Rais_Utils.h>';
	var name = this.getFieldValue("mat_name");
	var x = nsft(Blockly.Arduino.valueToCode(this, 'x', Blockly.Arduino.ORDER_ATOMIC));
	var y =	nsft(Blockly.Arduino.valueToCode(this, 'y', Blockly.Arduino.ORDER_ATOMIC));
	var state = Blockly.Arduino.valueToCode(this, 'state', Blockly.Arduino.ORDER_ATOMIC);
	return 'mset(' + name + ', ' + x + ', ' + y + ', ' + state + ');\n'; 
}